#pragma once

#include <iostream>
#include <chrono>
#include <iomanip>
#include <string>
#include <sstream>
#include <cmath>

#include <time.h>


// 临时存储数据用的结构体
// 如果你不准备给该工具类添加新功能, 你就不需要关心这个结构体
struct __timeData {
    time_t timestamp = -1;
    std::string formatDatatime = "";
    int ms = -1;
    int cs = -1;
    int ns = -1;
};

/* ======================= 工具类声明, 接口声明, 函数说明 =================== */
class TimestampUtil final   // final禁止继承
{
    /*
    public中的函数均为工具类接口函数, 可根据需求使用类名调用
*/
public:
    /**
    * 获取当前时间戳
    * @param time_level 时间戳精度, 范围[0, 3]
    *   time_level = 0, 返回10位时间戳, 精确到秒
    *   time_level = 1, 返回13位时间戳, 精确到毫秒, 参数默认值
    *   time_level = 2, 返回16位时间戳, 精确到微秒
    *   time_level = 3, 返回19位时间戳, 精确到纳秒
    * @return time_t 时间戳
     */
    static time_t getCurrentTimestamp(int time_level = 1);


    /**
     * 获取当前的日期字符串, 如 2023-04-06
    */
    static std::string getCurrentFormatDate();


    /**
     * 获取当前的时间字符串, 如 22:01:26
    */
    static std::string getCurrentFormatTime();


    /**
     * 获取当前时间节点的格式化字符串, 可设置精度
     * @param time_level 格式字符串的精度
     *   time_level = 0, 返回精度为秒级的格式化字符串,      如: 2023-04-06 22:21:51     默认值
     *   time_level = 1, 返回精度为毫秒级的格式化字符串,    如: 2023-04-06 22:21:51 266
     *   time_level = 2, 返回精度为微妙级时的格式化字符串,  如: 2023-04-06 22:21:51 266.527
     *   time_level = 3, 返回精度为纳妙级的时格式化字符串,  如: 2023-04-06 22:21:51 266.527.300
     * @return 当前时间的格式化字符串
    */
    static std::string getCurrentFormatDatetime(int time_level = 0);


    /**
     * 将任意精度的时间戳, 转化为格式化日期的字符串. 如: 2023-04-06
     * @param timestamp 10位/13位/16位/19位时间戳
     * @return 时间戳中日期部分的格式化字符串.
     *      如果返回nullptr, 说明传入的时间戳长度有误(传入的时间戳必须是10位, 13位, 16位, 19位的任意一种)
    */
    static std::string getFormatData(const time_t timestamp);


    /**
     * 将任意精度的时间戳, 转化为格式化时间的字符串(只获取时间部分, 精度秒). 如: 22:21:51
     * @param timestamp 10位/13位/16位/19位时间戳
     * @return 时间戳中的时间部分的格式化字符串
     *      如果返回nullptr, 说明传入的时间戳长度有误(传入的时间戳必须是10位, 13位, 16位, 19位的任意一种)
    */
    static std::string getFormatTime(const time_t timestamp);


    /**
     * 将任意精度的时间戳, 转化为格式化日期时间的字符串, 可设置精度
     * @param timestamp 10位/13位/16位/19位时间戳
     * @param time_level 精度水平
     *   time_level = 0, 返回精度为秒级的格式化字符串,      如: 2023-04-06 22:21:51     默认值
     *   time_level = 1, 返回精度为毫秒级的格式化字符串,    如: 2023-04-06 22:21:51 266
     *   time_level = 2, 返回精度为微妙级时的格式化字符串,  如: 2023-04-06 22:21:51 266.527
     *   time_level = 3, 返回精度为纳妙级的时格式化字符串,  如: 2023-04-06 22:21:51 266.527.300
     * @return 时间戳中的时间信息字符串
     *      如果返回nullptr, 说明传入的时间戳长度有误(传入的时间戳必须是10位, 13位, 16位, 19位的任意一种)
    */
    static std::string getFormatDataTime(time_t timestamp, int time_level = 0);



    /*
    private和protected权限的函数:
        如果你不准备为工具类添加新功能, 你就不需要关心下面的所有函数, 因为你无法调用到它们
        protected中主要是工具类内部计算时用到的函数
*/
private:
    // 禁止实例化
    TimestampUtil() = delete;

    // 无法在类外调用
protected:
    /** 检查/获取时间戳长度, 10位时间戳返回10, 13位返回13, 16位返回16, 19位会返回19 */
    static int checkBitLength(const time_t timestamp);

    /** 用于从操作系统中获取当前时间节点的数据(c++11标准) */
    static std::chrono::system_clock::time_point _getNow();

    /** 根据时间戳的长度返回精度水平, 10位时间戳精度为0. 13位精度为1, 16位精度为2, 19位精度为9,*/
    static int getTimeLevel(const time_t &timestamp);

    /** 根据时间戳计算毫秒, 微妙和纳秒的函数 */
    static void setFormatData(int time_level, const std::string &formatType, struct __timeData &timedata);

    /** 格式化日期计算函数 */
    static std::string buildFormatString(struct __timeData &timedata);

    /** 精度拟合函数, 当时间戳实际的精度 < 输入的精度, 修改输入精度为实际精度, 之后进行计算 */
    static int timestampGabFix(int input_level, __timeData &timedata);
};
